Image Color Reduction


Image Color Reduction

Because of limitations on space, memory or hardware, it is necessary to reduce the number of colors in an image. This is a two step process:
  1. Build color palette: a color palette is created from the main colors of the image
  2. Color replacement: each pixel in the image is replace with a color palette index

Debido a limitaciones en espacio, memoria o hardware, es necesario reducir el número de colores en una imagen. Esto es un proceso de dos pasos:
  1. Construir una paleta de colores: una paleta de colores es creada usando los colores principales de la imagen
  2. Reemplazo de colores: cada pixel en la imagen es reemplazado con un índice del color en la paleta

Octree

Wintempla implements the CG::Octree class to create an optimized color palette. An octree is composed of a root node with eight child nodes; each child node specializes in one range of colors as shown in the figure. All child nodes have other eight child nodes resulting in an octree with several levels. The child nodes after the root node separate the colors in eight ranges using the first bit of red, the first bit of green and the first bit of blue. The child nodes in the next level separate the colors in eight ranges using the second bit of each color. The octree expands until all bits in the colors have been used.
Wintempla implementa la clase CG::Octree para crear una paleta de colores optimizada. Un octree está compuesto de un nodo raíz con ocho nodos niños; cada nodo niño se especializa en un rango de colores como se muestra en la figura. Todos los nodos niño tiene otros nodos niño resultando en un octree con varios niveles. Los nodos niños después del nodo raíz separan los colores en otros rangos usando el primer bit del rojo, el primer bit del verde y el primer bit del azul. Los nodos niño en el siguiente nivel separan los colores en ocho rangos usando el segundo bit de cada color. El octree se expande hasta que todos los bits en los colores se han usado.

octree

Tip
The following code illustrates how to use the CG::Octree class to extract an optimized palette from an image.
El código siguiente ilustra cómo usar la clase CG::Octree para extraer una paleta optimizada desde una imagen.

Program.cpp

void Program::Window_Open(Win::Event& e)
{
     RGBQUAD input;
     CG::Octree octree;
     int i, j;
     int bitmap_height = some value;
     int bitmap_width = some value;
     for (i = 0; i < bitmap_height; i++)
     {
          for (j = 0; j < bitmap_width; j++, input++)
          {
               input = bitmap.pixels[i][j]; // Some function to extract the pixel of the image
               octree.AddColor(input.rgbtRed, input.rgbtGreen, input.rgbtBlue);
          }
     }
     vector<RGBQUAD> palette;
     octree.GeneratePalette(256, palette);
}


Get Nearest Color Palette Index

Once an optimized palette has been created, it is necessary to find the palette index for each pixel in the image. There are several methods to find the nearest color palette index. For instance, Win32 provides the ::GetNearestPaletteIndex function to find the palette index (see the CG::Palette class). A palette index can be quickly computed using another octree, see the CG::OctreeSearch class. The code below shows how to find the nearest palette index using the CG::OctreeSearch class.
Una vez que una paleta optimizada se ha creado, es necesario encontrar el índice de la paleta para cada pixel en la imagen. Hay varios métodos para encontrar el índice del color en la paleta. Por ejemplo, Win32 tien la función ::GetNearestPaletteIndex para encontrar el índice de la paleta (vea la clase CG::Palette). Un índice de paleta puede ser rápidamente calculado usando otro octree, vea la clase CG::OctreeSearch. El código de abajo muestra cómo encontrar el índice de la paleta usando la clase CG::OctreeSearch.

Program.cpp

void Program::Window_Open(Win::Event& e)
{
     //________________________________________ 1. Compute palette
     ...
     //________________________________________ 2. Find palette index for each pixel
     int i, j;
     CG::OctreeSearch octreeSearch;
     octreeSearch.Create(palette);
     unsigned char index, red, green, blue;
     for (i = 0; i < bitmap_height; i++)
     {
          for (j = 0; j < bitmap_width; j++, input++)
          {
               red = bitmap.pixel[i][j].rgbtRed;
               green = bitmap.pixel[i][j].rgbtGreen;
               blue = bitmap.pixel[i][j].rgbtBlue;
               index = octreeSearch.GetNearestColorIndex(palette, red, green, blue);
               ...
          }
     }
}


Problem 1
Create a Wintempla Window application called Compress to reduce the number of colors in a bitmap (*.bmp). You will need a 24 bits uncompress bitmap. To learn more about reducing the number of colors of an image, you should inspect the function CG::DIBitmap::CompressBitmap. After creating the project, open Wintempla and double click to anywhere in the window, go to the Event tab, and select the Paint event. Depending on the image size, the program will take some seconds to convert the bitmap.
Cree una Aplicación de Ventana de Wintempla llamada Compress para reducir el número de colores en un mapa de bits (*.bmp). Usted necesita´ra un bitmap de 24 bits sin comprimir. Para aprender más acerca de reducir el número de colores en una imagen, usted puede inspeccionar la función CG::DIBitmap::CompressBitmap. Después de crear el proyecto, abra Wintempla y haga clic doble en donde sea en la ventana, abra la pestaña de Event, y seleccione el evento de Paint.

CompressPaintEvent

CompressRun

BeachFolder

Compress.h
#pragma once //______________________________________ Compress.h
#include "Resource.h"
class Compress: public Win::Window
{
public:
     Compress()
     {
     }
     ~Compress()
     {
     }
     CG::DIBitmap bitmap;
     CG::DIBitmap bitmap256;
     ...
};


Compress.cpp
...
void Compress::Window_Open(Win::Event& e)
{
     //______________________________________________________1. Load the 24 bits color bitmap
     const wchar_t* error = bitmap.Load(L"C:\\john\\beach.bmp");
     if (error) this->MessageBox(error, L"Compress", MB_OK);
     //______________________________________________________ 2. Create a bitmap with 256 colors
     error = bitmap.CompressBitmap(256, bitmap256);
     if (error != NULL) this->MessageBox(error, L"Compress", MB_OK);
     //______________________________________________________3. Save the 256 colors bitmap
     error = bitmap256.Save(100, L"C:\\john\\beach256.bmp");
     if (error != NULL) this->MessageBox(error, L"Program", MB_OK);

     this->Repaint(NULL, true);
}

void Compress::Window_Paint(Win::Event& e)
{
     CG::Gdi gdi(hWnd, true, false);
     gdi.DrawBitmap(bitmap, 0, 0);
     gdi.DrawBitmap(bitmap256, 0, bitmap.GetHeight());
}


© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home